package com.qst.service.impl;

import com.qst.pojo.dto.CreateOrderDTO;
import com.qst.pojo.vo.OrderItemVO;
import com.qst.pojo.vo.OrderVO;
import com.qst.pojo.entity.Item;
import com.qst.pojo.entity.Order;
import com.qst.pojo.entity.OrderItem;
import com.qst.pojo.entity.Station;
import com.qst.pojo.entity.User;
import com.qst.repository.ItemRepository;
import com.qst.repository.OrderItemRepository;
import com.qst.repository.OrderRepository;
import com.qst.repository.StationRepository;
import com.qst.repository.UserRepository;
import com.qst.service.NotificationService;
import com.qst.service.OrderService;
import com.qst.util.OrderNoGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 订单服务实现类
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private NotificationService notificationService;
    
    @Autowired
    private OrderItemRepository orderItemRepository;
    
    @Autowired
    private ItemRepository itemRepository;
    
    @Autowired
    private StationRepository stationRepository;
    
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private OrderNoGenerator orderNoGenerator;

    /**
     * 创建订单（旧版本）
     */
    @Override
    @Transactional
    public Order createOrder(Order order) {
        try {
            // 生成订单编号
            String orderNo = generateOrderNo();
            order.setOrderNo(orderNo);
            
            // 设置默认状态
            if (order.getStatus() == null) {
                order.setStatus(Order.OrderStatus.pending);
            }
            
            // 保存订单
            Order savedOrder = orderRepository.save(order);
            
            // 发送新订单通知给站长
            notificationService.sendNewOrderNotification(savedOrder);
            
            return savedOrder;
        } catch (Exception e) {
            logger.error("创建订单失败", e);
            throw new RuntimeException("创建订单失败：" + e.getMessage());
        }
    }
    
    /**
     * 创建订单（新版本，使用DTO）
     */
    @Override
    @Transactional
    public Map<String, Object> createOrderFromDTO(CreateOrderDTO createOrderDTO, Integer customerId) {
        try {
            // 1. 验证必填字段
            if (createOrderDTO.getItems() == null || createOrderDTO.getItems().isEmpty()) {
                throw new RuntimeException("订单物品列表不能为空");
            }
            if (createOrderDTO.getPickupAddress() == null || createOrderDTO.getPickupAddress().trim().isEmpty()) {
                throw new RuntimeException("取货地址不能为空");
            }
            
            // 2. 验证用户信息完整性
            User customer = userRepository.findById(customerId)
                    .orElseThrow(() -> new RuntimeException("用户不存在"));
            
            if (customer.getRealName() == null || customer.getRealName().trim().isEmpty()) {
                throw new RuntimeException("用户未设置真实姓名，请先完善个人信息");
            }
            if (customer.getPhone() == null || customer.getPhone().trim().isEmpty()) {
                throw new RuntimeException("用户未设置联系电话，请先完善个人信息");
            }
            
            // 3. 计算订单总金额和总重量
            BigDecimal totalAmount = BigDecimal.ZERO;
            BigDecimal totalWeight = BigDecimal.ZERO;
            List<OrderItem> orderItems = new ArrayList<>();
            
            for (CreateOrderDTO.OrderItemDTO itemDTO : createOrderDTO.getItems()) {
                // 获取物品信息
                Item item = itemRepository.findById(itemDTO.getItemId())
                        .orElseThrow(() -> new RuntimeException("物品不存在：ID=" + itemDTO.getItemId()));
                
                // 检查物品状态
                if (item.getStatus() != Item.ItemStatus.active) {
                    throw new RuntimeException("物品 " + item.getName() + " 已暂停回收");
                }
                
                // 计算金额
                BigDecimal quantity = BigDecimal.valueOf(itemDTO.getQuantity());
                BigDecimal unitPrice = item.getPricePerUnit();
                BigDecimal subtotal = unitPrice.multiply(quantity).setScale(2, RoundingMode.HALF_UP);
                
                totalAmount = totalAmount.add(subtotal);
                
                // 计算重量（如果单位是kg）
                if ("kg".equalsIgnoreCase(item.getUnit())) {
                    totalWeight = totalWeight.add(quantity);
                }
                
                // 创建订单项（暂时不设置orderId）
                OrderItem orderItem = new OrderItem();
                orderItem.setItemId(item.getId());
                orderItem.setQuantity(quantity.intValue()); // 注意：这里需要根据实际需求调整
                orderItem.setUnitPrice(unitPrice);
                orderItem.setSubtotal(subtotal);
                orderItems.add(orderItem);
            }
            
            // 3. 确定站点ID
            Integer stationId = createOrderDTO.getStationId();
            if (stationId == null) {
                // 如果没有指定站点，分配一个默认站点（这里简单使用第一个站点）
                List<Station> stations = stationRepository.findAll();
                if (stations.isEmpty()) {
                    throw new RuntimeException("系统中没有可用的回收站点");
                }
                stationId = stations.get(0).getId();
            }
            
            // 4. 创建订单
            Order order = new Order();
            order.setOrderNo(generateOrderNo());
            order.setCustomerId(customerId);
            order.setStationId(stationId);
            order.setPickupAddress(createOrderDTO.getPickupAddress());
            order.setTotalAmount(totalAmount);
            order.setTotalWeight(totalWeight);
            order.setStatus(Order.OrderStatus.pending);
            order.setNotes(createOrderDTO.getNotes());
            
            // 解析预约时间
            if (createOrderDTO.getPickupTime() != null && !createOrderDTO.getPickupTime().isEmpty()) {
                try {
                    LocalDateTime pickupTime = LocalDateTime.parse(
                        createOrderDTO.getPickupTime(), 
                        DateTimeFormatter.ISO_DATE_TIME
                    );
                    order.setPickupTime(pickupTime);
                } catch (Exception e) {
                    logger.warn("解析预约时间失败: {}", createOrderDTO.getPickupTime(), e);
                }
            }
            
            // 5. 保存订单
            Order savedOrder = orderRepository.save(order);
            
            // 6. 保存订单项
            for (OrderItem orderItem : orderItems) {
                orderItem.setOrderId(savedOrder.getId());
                orderItemRepository.save(orderItem);
            }
            
            // 7. 发送新订单通知
            try {
                // 发送通知给站长
                notificationService.sendNewOrderNotification(savedOrder);
                // 发送确认邮件给客户
                notificationService.sendOrderConfirmationToCustomer(savedOrder);
            } catch (Exception e) {
                logger.error("发送订单通知失败", e);
                // 通知失败不影响订单创建
            }
            
            // 8. 返回订单详情
            Map<String, Object> result = new HashMap<>();
            result.put("orderNo", savedOrder.getOrderNo());
            result.put("orderId", savedOrder.getId());
            result.put("totalAmount", savedOrder.getTotalAmount());
            result.put("totalWeight", savedOrder.getTotalWeight());
            result.put("status", savedOrder.getStatus().name());
            result.put("createdAt", savedOrder.getCreatedAt());
            
            return result;
        } catch (Exception e) {
            logger.error("创建订单失败", e);
            throw new RuntimeException("创建订单失败：" + e.getMessage());
        }
    }

    /**
     * 更新订单状态
     */
    @Override
    @Transactional
    public Order updateOrderStatus(Integer orderId, Order.OrderStatus newStatus) {
        try {
            Order order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new RuntimeException("订单不存在"));
            
            // 记录旧状态
            String oldStatus = order.getStatus().name();
            
            // 更新状态
            order.setStatus(newStatus);
            
            // 根据新状态设置相应的时间戳
            LocalDateTime now = LocalDateTime.now();
            switch (newStatus) {
                case confirmed:
                    if (order.getConfirmedAt() == null) {
                        order.setConfirmedAt(now);
                    }
                    break;
                case in_progress:
                    if (order.getStartedAt() == null) {
                        order.setStartedAt(now);
                    }
                    break;
                case completed:
                    if (order.getCompletedAt() == null) {
                        order.setCompletedAt(now);
                    }
                    break;
                case cancelled:
                    // 取消订单时，如果没有完成时间，也设置一个（表示订单终止时间）
                    if (order.getCompletedAt() == null) {
                        order.setCompletedAt(now);
                    }
                    break;
                default:
                    break;
            }
            
            Order updatedOrder = orderRepository.save(order);
            
            // 发送订单状态更新通知给客户
            notificationService.sendOrderStatusUpdateNotification(updatedOrder, oldStatus, newStatus.name());
            
            return updatedOrder;
        } catch (Exception e) {
            logger.error("更新订单状态失败", e);
            throw new RuntimeException("更新订单状态失败：" + e.getMessage());
        }
    }

    /**
     * 获取所有订单
     */
    @Override
    public List<Order> getAllOrders() {
        return orderRepository.findAll();
    }

    /**
     * 根据ID获取订单
     */
    @Override
    public Order getOrderById(Integer orderId) {
        return orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在"));
    }

    /**
     * 获取站点订单列表
     */
    @Override
    public Map<String, Object> getStationOrders(Integer stationId, String status, Integer page, Integer pageSize) {
        try {
            Map<String, Object> result = new HashMap<>();
            
            // 创建分页请求，按创建时间降序排序
            Pageable pageable = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Direction.DESC, "createdAt"));
            
            // 根据是否有状态参数选择不同的查询方法
            Page<Order> orderPage;
            if (status != null && !status.isEmpty()) {
                try {
                    Order.OrderStatus orderStatus = Order.OrderStatus.valueOf(status);
                    orderPage = orderRepository.findByStationIdAndStatus(stationId, orderStatus, pageable);
                } catch (IllegalArgumentException e) {
                    logger.warn("无效的订单状态: {}", status);
                    orderPage = orderRepository.findByStationId(stationId, pageable);
                }
            } else {
                orderPage = orderRepository.findByStationId(stationId, pageable);
            }
            
            // 将Order实体转换为OrderVO
            List<OrderVO> orderVOList = new ArrayList<>();
            for (Order order : orderPage.getContent()) {
                orderVOList.add(OrderVO.fromEntity(order));
            }
            
            result.put("list", orderVOList);
            result.put("total", orderPage.getTotalElements());
            result.put("page", page);
            result.put("pageSize", pageSize);
            
            return result;
        } catch (Exception e) {
            logger.error("获取站点订单失败", e);
            throw new RuntimeException("获取站点订单失败：" + e.getMessage());
        }
    }

    /**
     * 获取客户订单列表
     */
    @Override
    public Map<String, Object> getCustomerOrders(Integer customerId, String status, Integer page, Integer pageSize) {
        try {
            Map<String, Object> result = new HashMap<>();
            
            // 创建分页请求，按创建时间降序排序
            Pageable pageable = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Direction.DESC, "createdAt"));
            
            // 根据是否有状态参数选择不同的查询方法
            Page<Order> orderPage;
            if (status != null && !status.isEmpty()) {
                try {
                    Order.OrderStatus orderStatus = Order.OrderStatus.valueOf(status);
                    orderPage = orderRepository.findByCustomerIdAndStatus(customerId, orderStatus, pageable);
                } catch (IllegalArgumentException e) {
                    logger.warn("无效的订单状态: {}", status);
                    orderPage = orderRepository.findByCustomerId(customerId, pageable);
                }
            } else {
                orderPage = orderRepository.findByCustomerId(customerId, pageable);
            }
            
            // 将Order实体转换为OrderVO，并加载订单项
            List<OrderVO> orderVOList = new ArrayList<>();
            for (Order order : orderPage.getContent()) {
                OrderVO orderVO = OrderVO.fromEntity(order);
                
                // 加载订单项
                List<OrderItem> orderItems = orderItemRepository.findByOrderId(order.getId());
                List<OrderItemVO> itemVOList = new ArrayList<>();
                for (OrderItem item : orderItems) {
                    OrderItemVO itemVO = new OrderItemVO();
                    itemVO.setId(item.getId());
                    itemVO.setOrderId(item.getOrderId());
                    itemVO.setItemId(item.getItemId());
                    itemVO.setQuantity(item.getQuantity());
                    itemVO.setUnitPrice(item.getUnitPrice());
                    itemVO.setSubtotal(item.getSubtotal());
                    
                    // 添加物品信息
                    if (item.getItem() != null) {
                        itemVO.setItemName(item.getItem().getName());
                        itemVO.setUnit(item.getItem().getUnit());
                    }
                    
                    itemVOList.add(itemVO);
                }
                orderVO.setItems(itemVOList);
                
                orderVOList.add(orderVO);
            }
            
            result.put("list", orderVOList);
            result.put("total", orderPage.getTotalElements());
            result.put("page", page);
            result.put("pageSize", pageSize);
            
            return result;
        } catch (Exception e) {
            logger.error("获取客户订单失败", e);
            throw new RuntimeException("获取客户订单失败：" + e.getMessage());
        }
    }
    
    /**
     * 获取订单统计信息
     */
    @Override
    public Map<String, Object> getOrderStats(Integer stationId, LocalDate startDate, LocalDate endDate) {
        try {
            Map<String, Object> stats = new HashMap<>();
            
            LocalDateTime startTime = startDate.atStartOfDay();
            LocalDateTime endTime = endDate.plusDays(1).atStartOfDay();
            
            // 统计当前状态的订单数量（不限时间）
            Long pending = orderRepository.countByStationIdAndStatus(stationId, Order.OrderStatus.pending);
            stats.put("pending", pending != null ? pending.intValue() : 0);
            
            // 统计处理中订单（包括confirmed和in_progress）
            Long confirmed = orderRepository.countByStationIdAndStatus(stationId, Order.OrderStatus.confirmed);
            Long inProgress = orderRepository.countByStationIdAndStatus(stationId, Order.OrderStatus.in_progress);
            int processing = (confirmed != null ? confirmed.intValue() : 0) + 
                            (inProgress != null ? inProgress.intValue() : 0);
            stats.put("processing", processing);
            
            // 统计已完成订单（不限时间）
            Long completed = orderRepository.countByStationIdAndStatus(stationId, Order.OrderStatus.completed);
            stats.put("completed", completed != null ? completed.intValue() : 0);
            
            // 统计指定时间范围的收益（用于"今日收益"）
            BigDecimal revenue = orderRepository.sumTotalAmountByStationIdAndTimeRange(
                    stationId, startTime, endTime);
            stats.put("todayRevenue", revenue != null ? revenue.doubleValue() : 0.0);
            
            return stats;
        } catch (Exception e) {
            logger.error("获取订单统计失败", e);
            // 返回默认值而不是抛出异常
            Map<String, Object> defaultStats = new HashMap<>();
            defaultStats.put("pending", 0);
            defaultStats.put("processing", 0);
            defaultStats.put("completed", 0);
            defaultStats.put("todayRevenue", 0.0);
            return defaultStats;
        }
    }

    /**
     * 获取订单详情（包含订单项）
     */
    @Override
    public Map<String, Object> getOrderDetail(Integer orderId) {
        try {
            Order order = orderRepository.findById(orderId)
                    .orElseThrow(() -> new RuntimeException("订单不存在"));
            
            // 转换为VO
            OrderVO orderVO = OrderVO.fromEntity(order);
            
            // 获取订单项
            List<OrderItem> orderItems = orderItemRepository.findByOrderId(orderId);
            List<OrderItemVO> itemVOList = new ArrayList<>();
            for (OrderItem item : orderItems) {
                OrderItemVO itemVO = new OrderItemVO();
                itemVO.setId(item.getId());
                itemVO.setOrderId(item.getOrderId());
                itemVO.setItemId(item.getItemId());
                itemVO.setQuantity(item.getQuantity());
                itemVO.setUnitPrice(item.getUnitPrice());
                itemVO.setSubtotal(item.getSubtotal());
                
                // 如果有关联的物品信息
                if (item.getItem() != null) {
                    itemVO.setItemName(item.getItem().getName());
                }
                
                itemVOList.add(itemVO);
            }
            
            orderVO.setItems(itemVOList);
            
            Map<String, Object> result = new HashMap<>();
            result.put("order", orderVO);
            result.put("items", itemVOList);
            
            return result;
        } catch (Exception e) {
            logger.error("获取订单详情失败", e);
            throw new RuntimeException("获取订单详情失败：" + e.getMessage());
        }
    }

    /**
     * 生成订单编号
     * 使用 OrderNoGenerator 工具类生成
     * 格式: RC + 年月日 + 序号（例如：RC20251001001）
     */
    private String generateOrderNo() {
        return orderNoGenerator.generate();
    }
}

